using System.Collections;
using Evaluant.Uss.Commands;
using Evaluant.Uss.Common;
using System.Globalization;

namespace Evaluant.Uss.Hub
{
	/// <summary>
	/// 
	/// </summary>
	/// <remarks>
	/// The ids that are returned are those from the default persistence engine. Thus a TraceEngine can't be used 
	/// as a Default one.
	/// </remarks>
	public class HubEngine : IPersistenceEngine 
	{
		private IPersistenceEngine[] _Delegators;
		public IPersistenceEngine[] Delegators
		{
			get { return _Delegators; }
			set 
			{ 
				_Delegators = value;
			}
		}

		public CultureInfo Culture
		{
			get { return null; }
			set { }
		}

		private int _DefaultEngineIndex = 0;
		/// <summary>
		/// Gets or set the index of the engine used for reading
		/// </summary>
		public int DefaultEngineIndex
		{
			get { return _DefaultEngineIndex; }
			set { _DefaultEngineIndex = value; }
		}

		public HubEngine(IPersistenceEngine[] delegators)
		{
			_Delegators = delegators;
		}

		public EntitySet Load(string opath)
		{
			return Load(opath, new string[0]);
		}

		public EntitySet Load(string opath, string[] attributes)
		{
			return Load(opath, attributes, null, 1, 0);
		}

		public EntitySet Load(string opath, string orderby, int first, int max)
		{
			return Load(opath, new string[0], orderby, first, max);
		}

		public EntitySet LoadWithId(string type, string[] id)
		{
			return LoadWithId(type, id, new string[0]);
		}

		public Entity LoadWithId(string type, string id)
		{
			EntitySet result = LoadWithId(type, new string[] { id });
			return result.Count > 0 ? result[0] : null;
		}

		public void LoadReference(Entity entity)
		{
			LoadReference(new Entity[] { entity });
		}

		public void LoadReference(Entity entity, string[] references)
		{
			LoadReference(new Entity[] { entity }, references);
		}

		public void LoadReference(IEnumerable entities)
		{
			LoadReference(entities, new string[0]);
		}

		public void InitializeRepository()
		{
			foreach(IPersistenceEngine engine in _Delegators)
				engine.InitializeRepository();
		}

		public void Initialize()
		{
			foreach(IPersistenceEngine engine in _Delegators)
				engine.Initialize();			
		}


        public virtual EntitySet Load(OPath.OPathQuery opath, string[] attributes, string orderby, int first, int max)
        {
            return _Delegators[_DefaultEngineIndex].Load(opath, attributes, orderby, first, max);
        }

		public virtual EntitySet Load(string opath, string[] attributes, string orderby, int first, int max)
		{
			return _Delegators[_DefaultEngineIndex].Load(opath, attributes, orderby, first, max);
		}

		public virtual void LoadReference(System.Collections.IEnumerable entities, string[] references)
		{
			_Delegators[_DefaultEngineIndex].LoadReference(entities, references);
		}

		public virtual EntitySet LoadWithId(string type, string[] id, string[] attributes)
		{
			return _Delegators[_DefaultEngineIndex].LoadWithId(type, id, attributes);
		}

        public virtual object LoadScalar(string opath)
        {
            return _Delegators[_DefaultEngineIndex].LoadScalar(opath);
        }

        public virtual object LoadScalar(OPath.OPathQuery opath)
        {
            return _Delegators[_DefaultEngineIndex].LoadScalar(opath);
        }

		public void BeforeProcessCommands(Transaction tx)
		{
			foreach(IPersistenceEngine pe in _Delegators)
				pe.BeforeProcessCommands(tx);
		}

		public void ProcessCommands(Transaction tx)
		{
			foreach(IPersistenceEngine pe in _Delegators)
				pe.ProcessCommands(tx);
		}

		public void AfterProcessCommands(Transaction tx)
		{
			foreach(IPersistenceEngine pe in _Delegators)
				pe.AfterProcessCommands(tx);
		}

		public Evaluant.Uss.Models.Model Model
		{
			get { return _Delegators[_DefaultEngineIndex].Model; }
		}
	}
}
